﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AMS.Chess.CommonLayer
{
    public class PawnMove : AMove
    {
        
        public PawnMove(AChessBoard board)
            : base(board)
        {

        }

        protected override List<ABoardPosition> GenerateMoves(AChessPiece movingPiece, ABoardPosition startPosition)
        {
            // valid position and valid piece/position match already verified with board

            StandardBoardPosition originalPosition = startPosition as StandardBoardPosition;
            if (originalPosition == null)
                throw new ArgumentException("Invalid position type");

            StandardChessBoard board = _board as StandardChessBoard;
            if (board == null)
                throw new ArgumentException("Invalid board");

            List<ABoardPosition> possibleMoves = new List<ABoardPosition>();

            Console.WriteLine("A Pawn moves forward only.  PawnMove is generating possible positions.");

            GeneratePawnMoves(board, movingPiece, originalPosition, possibleMoves);

            return possibleMoves;
        }

        public static void GeneratePawnMoves(StandardChessBoard board, AChessPiece movingPiece, StandardBoardPosition originalPosition, List<ABoardPosition> possibleMoves)
        {
            // White pawn moves up, Black pawn moves down
            // Pawn cannot move forward if blocked by any piece

            StandardBoardPosition upOne;
            bool upOneValid = false;
            int startRank = movingPiece.Color == ChessColor.White ? 2 : 7;
            StandardBoardPosition upTwo;
            StandardBoardPosition upLeft;
            StandardBoardPosition upRight;

            if (movingPiece.Color == ChessColor.White)
            {
                upOne = new StandardBoardPosition(originalPosition.Rank + 1, originalPosition.File);
                upTwo = new StandardBoardPosition(originalPosition.Rank + 2, originalPosition.File);
                upLeft = new StandardBoardPosition(originalPosition.Rank + 1, (char)((int)originalPosition.File - 1));
                upRight = new StandardBoardPosition(originalPosition.Rank + 1, (char)((int)originalPosition.File + 1));
            }
            else
            {
                upOne = new StandardBoardPosition(originalPosition.Rank - 1, originalPosition.File);
                upTwo = new StandardBoardPosition(originalPosition.Rank - 2, originalPosition.File);
                upLeft = new StandardBoardPosition(originalPosition.Rank - 1, (char)((int)originalPosition.File - 1));
                upRight = new StandardBoardPosition(originalPosition.Rank - 1, (char)((int)originalPosition.File + 1));
            }

            upOneValid = TestForward(upOne, board, possibleMoves);

            // Pawn can move 2 space only if it's pawn's first move
            // get piece position and see if rank is 2 (White) or 7 (Black)
            if (originalPosition.Rank == startRank && upOneValid)
            {
                TestForward(upTwo, board, possibleMoves);
            }

            // Pawn can only move diagonally forward if capturing enemy piece
            TestDiagonal(upLeft, board, movingPiece.Color, possibleMoves);
            TestDiagonal(upRight, board, movingPiece.Color, possibleMoves);
        }

        private static bool ValidateAgainstBoard(StandardBoardPosition position)
        {
            return position.Rank <= StandardChessBoard.MaxRank && position.Rank >= StandardChessBoard.MinRank &&
                position.File <= StandardChessBoard.MaxFile && position.File >= StandardChessBoard.MinFile;
        }

        private static bool TestForward(StandardBoardPosition targetPosition, StandardChessBoard board, List<ABoardPosition> possibleMoves)
        {
            if (ValidateAgainstBoard(targetPosition))
            {
                AStandardChessPiece piece = board.GetPiece(targetPosition) as AStandardChessPiece;

                if (piece == null) //empty?
                {
                    possibleMoves.Add(targetPosition);  // legit target space
                    return true;
                }
            }

            return false;
        }

        private static bool TestDiagonal(StandardBoardPosition targetPosition, StandardChessBoard board, ChessColor pieceColor, List<ABoardPosition> possibleMoves)
        {
            if (ValidateAgainstBoard(targetPosition))
            {
                AStandardChessPiece piece = board.GetPiece(targetPosition) as AStandardChessPiece;

                if (piece != null && piece.Color != pieceColor) //enemy?
                {
                    possibleMoves.Add(targetPosition);  // legit target space
                    return true;
                }
            }

            return false;
        }
    }
}
